#include <stdio.h>
#include <stdint.h>
#include <stddef.h>
#include <string.h>
#include "cJSON.h"

#include "esp_log.h"
#include "mqtt_client.h"
#include "../memPool/memPool.h"
#include "mqttClient.h"

#define ALIYUN_PRODUCT_KEY    "a1UcBeFcm6Y"
#define ALIYUN_DEVICE_NAME    "TEST"
#define ALIYUN_DEVICE_SECRET  "53fb0d483843f6bfaaf66eb370708548"
#define ALIYUN_REGION         "cn-shanghai"
#define ALIYUN_PASSWORD       "b7bb4f27d40ba89d2611b093ce23152e2e093c360e678b6a173c21305c45915f"
#define ALIYUN_USERNAME       "TEST&a1UcBeFcm6Y"
#define ALIYUN_CLIENT_ID      "a1UcBeFcm6Y.TEST|securemode=2,signmethod=hmacsha256,timestamp=1756882495993|"

#define ALIYUN_URI            "mqtt://a1UcBeFcm6Y.iot-as-mqtt.cn-shanghai.aliyuncs.com"

#define MODULE_KEY            "Temperature"  // 模块标识符
#define MAX_QUEUE_LENGTH      20
// MQTT客户端句柄
esp_mqtt_client_handle_t      aliyun_mqtt_client;

static const char *TAG = "mqtt:";

static QueueHandle_t mqtt_data_queue;
TimerHandle_t mqttReportTimer;
static void mqttReport(TimerHandle_t xTimer);
static bool publish_temperature_data(float temperature);

static void mqtt_event_handler(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data)
{
    ESP_LOGD(TAG, "Event dispatched from event loop base=%s, event_id=%" PRIi32 "", base, event_id);
    esp_mqtt_event_handle_t event = event_data;
    esp_mqtt_client_handle_t client = event->client;
    int msg_id;
    switch ((esp_mqtt_event_id_t)event_id) {
    case MQTT_EVENT_CONNECTED:
        ESP_LOGI(TAG, "MQTT_EVENT_CONNECTED");

        msg_id = esp_mqtt_client_subscribe(client, "test/sw", 0);
        ESP_LOGI(TAG, "sent subscribe successful, msg_id=%d", msg_id);

        break;
    case MQTT_EVENT_DISCONNECTED:
        ESP_LOGI(TAG, "MQTT_EVENT_DISCONNECTED");
        break;

    case MQTT_EVENT_SUBSCRIBED:
        ESP_LOGI(TAG, "MQTT_EVENT_SUBSCRIBED, msg_id=%d", event->msg_id);
        break;
    case MQTT_EVENT_UNSUBSCRIBED:
        ESP_LOGI(TAG, "MQTT_EVENT_UNSUBSCRIBED, msg_id=%d", event->msg_id);
        break;
    case MQTT_EVENT_PUBLISHED:
        ESP_LOGI(TAG, "MQTT_EVENT_PUBLISHED, msg_id=%d", event->msg_id);
        break;
    case MQTT_EVENT_DATA:
        ESP_LOGI(TAG, "MQTT_EVENT_DATA");
        char* token;
        char* output_buffer;
        uint8_t cnt = 0,keyFlag = 0,deviceFlag = 0;
        static size_t buffer_size = 0;
        token = strtok(event->topic, "/");
        while(token != NULL)
        {
            token = strtok(NULL, "/");
            if(strncmp(token, ALIYUN_PRODUCT_KEY, strlen(ALIYUN_PRODUCT_KEY)) == 0)
            {
                keyFlag = 1;
            }
            if(strncmp(token, ALIYUN_DEVICE_NAME, strlen(ALIYUN_DEVICE_NAME)) == 0)
            {
                deviceFlag = 1;
            }
            if(cnt++ > 3)
            {
                break;
            }
        }
        if(keyFlag == 1 && deviceFlag == 1)
        {
            ESP_LOGI("mqtt event","DATA=%.*s\r\n", event->data_len, event->data);
            output_buffer = (char*)allocate_from_pool_mini(event->data_len + 128, &buffer_size);
            strncpy(output_buffer, event->data, event->data_len);
            mqtt_message_t msg = {
                .data = (uint8_t*)output_buffer,
                .length = event->data_len,
            };
            if (xQueueSend(mqtt_data_queue, &msg, pdMS_TO_TICKS(100)) != pdTRUE) {
                ESP_LOGE(TAG, "Queue full, dropping message");
                free_to_pool((uint8_t*)output_buffer);
            }
            ESP_LOGI(TAG,"TOPIC COMPARE SUCCESS");
        }
        else
        {
            ESP_LOGE(TAG,"TOPIC COMPARE ERROR");
        }
        break;
    case MQTT_EVENT_ERROR:
        ESP_LOGI(TAG, "MQTT_EVENT_ERROR");
        if (event->error_handle->error_type == MQTT_ERROR_TYPE_TCP_TRANSPORT) {
            ESP_LOGI(TAG, "Last errno string (%s)", strerror(event->error_handle->esp_transport_sock_errno));

        }
        break;
    default:
        ESP_LOGI(TAG, "Other event id:%d", event->event_id);
        break;
    }
}

//初始化MQTT客户端
void mqtt_app_start(void) {
    // MQTT配置
    esp_mqtt_client_config_t mqtt_cfg = {
        .broker = {
            .address = {
                .uri = "mqtts://" ALIYUN_PRODUCT_KEY ".iot-as-mqtt." ALIYUN_REGION ".aliyuncs.com:1883",
            },
        },
        .credentials = {
            .client_id = ALIYUN_CLIENT_ID,
            .username = ALIYUN_USERNAME,
            .authentication = {
                .password = ALIYUN_PASSWORD,
                .certificate = NULL, // 阿里云使用标准CA证书，通常不需要额外配置
            }
        },
        .session = {
            .keepalive = 60,
        },
    };

    aliyun_mqtt_client = esp_mqtt_client_init(&mqtt_cfg);
    esp_mqtt_client_register_event(aliyun_mqtt_client, ESP_EVENT_ANY_ID, mqtt_event_handler, NULL);
    esp_mqtt_client_start(aliyun_mqtt_client);
}

void TaskMqtt(void* param)
{
    mqtt_message_t msg;

    mqtt_app_start();
    init_memory_pool_mini();
    mqtt_data_queue = xQueueCreate(MAX_QUEUE_LENGTH, sizeof(mqtt_message_t));
    mqttReportTimer = xTimerCreate("mqtt report", pdMS_TO_TICKS(10000), 1, NULL, mqttReport);
    xTimerStart(mqttReportTimer, portMAX_DELAY);
    while (1)
    {
        if (xQueueReceive(mqtt_data_queue, &msg, portMAX_DELAY)) 
        {
            ESP_LOGI("work task","DATA=%.*s\r\n", msg.length, msg.data);
            free_to_pool_mini(msg.data);
        }
    }
    vTaskDelete(NULL);
}

static void mqttReport(TimerHandle_t xTimer)
{
    ESP_LOGI(TAG, "PUBLISH TEMP DATA");
    publish_temperature_data(19.3);
}

static bool publish_temperature_data(float temperature) 
{
    if (aliyun_mqtt_client == NULL) {
        ESP_LOGE("ALIYUN", "MQTT client not initialized");
        return false;
    }

    // 创建JSON数据
    cJSON *root = cJSON_CreateObject();
    cJSON *params = cJSON_CreateObject();
    
    // 添加温度数据
    cJSON_AddNumberToObject(params, "temperature", temperature);

    
    // 添加时间戳
    cJSON_AddStringToObject(params, "Timestamp", "2024-01-01T12:00:00Z");
    
    // 组装阿里云要求的格式
    cJSON_AddNumberToObject(root, "id", 10); // 随机消息ID
    cJSON_AddStringToObject(root, "version", "1.0");
    cJSON_AddStringToObject(root, "method", "thing.event.property.post");
    cJSON_AddItemToObject(root, "params", params);

    // 生成JSON字符串
    char *json_str = cJSON_PrintUnformatted(root);
    cJSON_Delete(root);

    if (json_str == NULL) {
        ESP_LOGE("ALIYUN", "Failed to create JSON string");
        return false;
    }

    // 构造主题
    char topic[256];
    snprintf(topic, sizeof(topic), 
             "/sys/%s/%s/thing/event/property/post", 
             ALIYUN_PRODUCT_KEY, ALIYUN_DEVICE_NAME);

    // 发布消息
    int msg_id = esp_mqtt_client_publish(aliyun_mqtt_client, topic, json_str, 
                                        strlen(json_str), 1, 0);
    
    free(json_str);

    if (msg_id == -1) {
        ESP_LOGE("ALIYUN", "Failed to publish temperature data");
        return false;
    }

    ESP_LOGI("ALIYUN", "Temperature data published, msg_id: %d", msg_id);
    return true;
}